/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.pc9.pswing.components.filebrowser;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Stack;
import javax.swing.DefaultListModel;


/**
 *
 * @author paulocanedo
 */
public final class FileBrowserListModel extends DefaultListModel {

    private FileBrowserFilter fileFilter;
    private String userHome;
    private Stack<File> backControlStack = new Stack<File>();
    private Stack<File> forwardControlStack = new Stack<File>();
    private File currentFolder;
    private List<PFileView> currentViewFiles = new ArrayList<PFileView>();

    public FileBrowserListModel() {
        this.fileFilter = new FileBrowserFilter();

        userHome = System.getProperty("user.home");

        File fileHome = new File(userHome);
        setFolderView(fileHome);
    }

    private void setFolderView(File folder) {
        setFolderView(folder, false);
    }

    private void setFolderView(File folder, boolean forceRefresh) {
        int oldSize = currentViewFiles.size();
        if (currentFolder != null) {
            if ((!forceRefresh) && currentFolder.equals(folder)) {
                return;
            }
        }

        this.currentFolder = folder;
        this.currentViewFiles.clear();
        File[] listFiles = folder.listFiles(fileFilter);
        for (File f : listFiles) {
            currentViewFiles.add(new PFileView(f));
        }

        Collections.sort(currentViewFiles, new Comparator<PFileView>() {

            @Override
            public int compare(PFileView o1, PFileView o2) {
                if (o1.getFile().isDirectory() && o2.getFile().isFile()) {
                    return -1;
                }
                if (o2.getFile().isDirectory() && o1.getFile().isFile()) {
                    return 1;
                }
                return o1.getFile().compareTo(o2.getFile());
            }
        });
        fireDataChanged(oldSize, currentViewFiles.size());
    }

    private void fireDataChanged(int oldSize, int newSize) {
        if (oldSize > 0) {
            fireIntervalRemoved(this, 0, oldSize);
        }

        if (newSize > 0) {
            fireIntervalAdded(this, 0, newSize);
        }
    }

    public void setPrefixFilter(String prefix) {
        fileFilter.setFilter(prefix);
        refresh();
    }

    public void refresh() {
        setFolderView(currentFolder, true);
    }

    public File back() {
        if (!backControlStack.isEmpty()) {
            forwardControlStack.push(currentFolder);
            setFolderView(backControlStack.pop());
        }

        return currentFolder;
    }

    public File forward() {
        if (!forwardControlStack.isEmpty()) {
            backControlStack.push(currentFolder);
            setFolderView(forwardControlStack.pop());
        }

        return currentFolder;
    }

    public void open(File folder) {
        if (!folder.equals(currentFolder)) {
            backControlStack.push(currentFolder);
            forwardControlStack.clear();
        }
        setFolderView(folder);
    }

    public File getCurrentFolder() {
        return currentFolder;
    }
    
    @Override
    public int getSize() {
        return currentViewFiles.size();
    }

    @Override
    public Object getElementAt(int index) {
        return currentViewFiles.get(index);
    }
}
class FileBrowserFilter implements FileFilter {

    private boolean filterHidden = true;
    private String filter = null;

    public FileBrowserFilter() {
    }

    public FileBrowserFilter(boolean acceptHidden) {
        this.filterHidden = acceptHidden;
    }

    public FileBrowserFilter(boolean acceptHidden, String prefixFilter) {
        this.filterHidden = acceptHidden;
        this.filter = prefixFilter;
    }

    @Override
    public boolean accept(File pathname) {
        boolean flag = true;
        if (filterHidden) {
            flag = isFileVisible(pathname);
        }

        if (filter != null && !filter.isEmpty()) {
            flag = isTextMatch(pathname, filter);
        }

        return flag;
    }

    public boolean isFilterHidden() {
        return filterHidden;
    }

    public void setFilterHidden(boolean filterHidden) {
        this.filterHidden = filterHidden;
    }

    public String getFilter() {
        return filter;
    }

    public void setFilter(String prefixFilter) {
        this.filter = prefixFilter;
    }

    private boolean isTextMatch(File pathname, String prefixName) {
        return pathname.getName().toLowerCase().contains(prefixName);
    }

    private boolean isFileVisible(File pathname) {
        return (!pathname.isHidden()) && (!pathname.getName().endsWith("~")) && (!pathname.getName().startsWith("."));
    }
    
}
